from datetime import date, timedelta
from random import uniform, randint, choice
import string

characters = string.letters + string.digits
def_converter = lambda x : x

def populate(datatype = 'string', size  = 10,
             start = None, end = None, 
             converter = None, 
             choice_from = None,
             **kwargs):
    '''Utility function for populating lists with random data. Useful for populating
database with data for testing. Supported data-types
    
    * *string*
        For example::
            
            populate('string',100, min_len=3, max_len=10)
        
        create a 100 elements list with random strings
        with random length between 3 and 10
        
    * *date*
        For example::
            
            from datetime import date
            populate('date',200, start = date(1997,1,1), end = date.today())
        
        create a 200 elements list with random datetime.date objects between *start* and *end*
        
    * *integer*
        For example::
            
            populate('integer',200, start = 0, end = 1000)
        
        create a 200 elements list with random int between *start* and *end*
        
    * *floats*
        For example::
            
            populate('integer',200, start = 0, end = 10)
        
        create a 200 elements list with random floats between *start* and *end*

    * *choice* (elements of an iterable)
        For example::
            
            populate('choice', 200, choice_from = ['pippo','pluto','blob'])
        
        create a 200 elements list with random elements from *choice_from*
    '''
    data = []
    converter = converter or def_converter
    if datatype == 'string':
        for s in range(size):
            data.append(converter(random_string(**kwargs)))
    elif datatype == 'date':
        date_end   = end or date.today()
        date_start = start or date(1990,1,1)
        delta    = date_end - date_start
        for s in range(size):
            data.append(converter(random_date(date_start, delta.days)))
    elif datatype == 'integer':
        start = start or 0
        end = end or 1000000
        for s in range(size):
            data.append(converter(randint(start,end)))
    elif datatype == 'float':
        start = start or 0
        end = end or 10
        for s in range(size):
            data.append(converter(uniform(start,end)))
    elif datatype == 'choice':
        for s in range(size):
            data.append(choice(choice_from))
    else:
        for s in range(size):
            data.append(converter(random_string(**kwargs)))
    return data

def random_string(min_len = 3, max_len = 20, **kwargs):
    len = randint(min_len,max_len)
    s   = [choice(characters) for s in range(len)]
    return ''.join(s)

def random_date(date_start, delta):
    return date_start + timedelta(days = randint(0,delta))
    
    
    
